package ClonePraDemo;

import java.math.BigDecimal;

/**
 * @time: 2022/3/31/031 11:34
 * @author: Zhurunhe
 * @Version：1 浅拷贝与深拷贝
 */
public class CloneDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        cloneFS();
    }

    //(1) 引用拷贝
    public static void cloneF() {
        //创建一个指向对象的引用变量的拷贝。
        Staff staffOne = new Staff(1001, "小明", new BigDecimal("3750"));
        Staff staffTwo = staffOne;
        System.out.println(staffOne);
        System.out.println(staffTwo);
        /**
         *
         * ClonePraDemo.Staff@36baf30c  (staffOne)
         * ClonePraDemo.Staff@36baf30c  (staffTwo)
         *
         * 两个对象指向的对象地址相同，指向的是同一个的对象，两个对象只是对 new Staff(1001, "小明", new BigDecimal("3750")); 进行引用
         * 引用拷贝
         */
    }
    //(2) 对象拷贝 两个对象指向的对象地址不同，对象拷贝是将重新拷贝多一份对象 (浅拷贝和深拷贝都属于对象拷贝)
    //(3) 浅拷贝
    public static void cloneS() throws CloneNotSupportedException {
        //创建一个指向对象的引用变量的拷贝。
        Staff Boss =new Staff();
        Staff staffOne = new Staff(1002, "小明", new BigDecimal("3750"),Boss);
        Staff staffTwo = (Staff) staffOne.clone();
        System.out.println("staffOne地址："+staffOne);
        System.out.println("staffTwo地址："+staffTwo);
        System.out.println("staffOne的Salary地址："+staffOne.getSalary().hashCode());
        System.out.println("staffTwo的Salary地址："+staffTwo.getSalary().hashCode());
        System.out.println("OneBoss地址:"+staffOne.getBoss());
        System.out.println("TwoBoss地址:"+staffTwo.getBoss());
        /**
         *
         * staffOne地址：ClonePraDemo.Staff@36baf30c
         * staffTwo地址：ClonePraDemo.Staff@7a81197d
         * staffOne的Salary地址：116250
         * staffTwo的Salary地址：116250
         * OneBoss地址:ClonePraDemo.Staff@5ca881b5
         * TwoBoss地址:ClonePraDemo.Staff@5ca881b5
         *
         * 指向的对象地址不相同说明创建了两个新对象，两个对象指向的对象地址也不相同，
         * 但拷贝的对象中的子对象仍指向同一个地址(OneBoss地址 TwoBoss地址 相同)
         * 浅拷贝
         */
    }
    public static void cloneFS() throws CloneNotSupportedException {
        //创建一个指向对象的引用变量的拷贝。
        Staff Boss =new Staff();
        Staff staffOne = new Staff(1003, "小明", new BigDecimal("3750"),Boss);
        Staff staffTwo = (Staff) staffOne.clone2();
        System.out.println("staffOne地址："+staffOne);
        System.out.println("staffTwo地址："+staffTwo);
        System.out.println("staffOne的Salary地址："+staffOne.getSalary().hashCode());
        System.out.println("staffTwo的Salary地址："+staffTwo.getSalary().hashCode());
        System.out.println("OneBoss地址:"+staffOne.getBoss());
        System.out.println("TwoBoss地址:"+staffTwo.getBoss());
        /**
         *
         * staffOne地址：ClonePraDemo.Staff@36baf30c
         * staffTwo地址：ClonePraDemo.Staff@7a81197d
         * OneBoss地址:ClonePraDemo.Staff@5ca881b5
         * TwoBoss地址:ClonePraDemo.Staff@24d46ca6
         *
         * 指向的对象地址不相同说明创建了两个新对象，两个对象指向的对象地址也不相同，
         * 但拷贝的对象中的子对象指向不同的地址(OneBoss地址 TwoBoss地址 不相同)
         * 深拷贝
         */
    }
}

class Staff implements Cloneable{
    private int id;
    private String name;
    private BigDecimal salary;
    private Staff boss;
    public Staff() {
    }

    public Staff(int id, String name, BigDecimal salary, Staff boss) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.boss = boss;
    }

    public Staff getBoss() {
        return boss;
    }

    public void setBoss(Staff boss) {
        this.boss = boss;
    }
    //浅拷贝
    public Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        return obj;
    }
    //深拷贝
    public Object clone2() throws CloneNotSupportedException {
        Staff obj = (Staff) super.clone();
        if (obj.getBoss()!=null){
            obj.setBoss((Staff) obj.getBoss().clone());
        }
        return obj;
    }

    public Staff(int id, String name, BigDecimal salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getSalary() {
        return salary;
    }

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
}